// 移动端适配 16px -> 1.6rem
let defaultFontSize = '16px';
document.documentElement.style.fontSize = defaultFontSize;
document.documentElement.clientWidth / 37.5 + 'px';

(() => {
  const idioms = ['诗情画意', '南来北往', '一团和气', '落花流水'],
    oCharCellGroup = document.querySelector('.char-cell-group'),
    //获取所有空格盒子
    oBlanks = document.querySelectorAll('.blank-cell-group .wrapper');

  let charCollection = [],
    //该池子保存所有字体盒子的偏移量数据
    charAreas = [],
    //该池子保存所有空格盒子的坐标数据
    blankAreas = [],
    //该池子保存某个盒子的字体和节点
    resArr = [undefined, undefined, undefined, undefined],
    oChars = null,
    cellW = 0,
    cellH = 0,
    //当前屏幕可视区域的初始触摸鼠标坐标
    startX = 0,
    startY = 0,
    //新的偏移坐标
    cellX = 0,
    cellY = 0,
    mouseDistanceX = 0,
    mouseDistanceY = 0;

  const init = () => {
    //1.拿到散乱成语的单个字体组成的新数组
    charCollection = formatCharsArr();
    //2.渲染字体到视图上
    render();

    //获取所有字体盒子
    oChars = oCharCellGroup.querySelectorAll('.cell-item .wrapper');

    //通过缓存池获取初始偏移量数据
    getAreas(oBlanks, blankAreas);

    getAreas(oChars, charAreas);

    bindEvent();
  };

  function bindEvent() {
    let oChar = null;

    //给每个字体单独绑定事件
    for (let i = 0; i < oChars.length; i++) {
      oChar = oChars[i];

      /**
       * 备注：
       * 当一个或多个触摸点与触控设备表面接触时触发 touchstart 事件
       * 当触点在触控平面上移动时触发 touchmove 事件
       * 当触点离开触控平面时触发 touchend 事件
       */

      oChar.addEventListener('touchstart', handleTouchStart, false);
      oChar.addEventListener('touchmove', handleTouchMove, false);
      oChar.addEventListener('touchend', handleTouchEnd, false);
    }
  }

  function handleTouchStart(e) {
    //获取当前盒子宽高
    cellW = this.offsetWidth;
    cellH = this.offsetHeight;

    //获取当前盒子偏移量
    cellX = this.offsetLeft;
    cellY = this.offsetTop;

    //获取当前屏幕可视区域的初始触摸鼠标坐标
    startX = e.touches[0].clientX;
    startY = e.touches[0].clientY;

    //计算获取鼠标坐标到当前盒子边缘距离(范围仅限于当前点中盒子 1-75 px)
    mouseDistanceX = startX - cellX;
    mouseDistanceY = startY - cellY;

    //将盒子宽高和偏移量的单位像素转为rem
    this.style.width = pxToRem(cellW);
    this.style.height = pxToRem(cellH);

    //设置位置
    setPosition(this, { x: cellX, y: cellY });

    //固定定位
    this.style.position = 'fixed';
  }

  function handleTouchMove(e) {
    //阻止窗口回弹的默认行为
    e.preventDefault();

    //获取当前屏幕可视区域的新的触摸鼠标坐标
    const moveX = e.touches[0].clientX,
      moveY = e.touches[0].clientY;

    //新的偏移距离 = 新的鼠标坐标 - 固定的距离
    cellX = moveX - mouseDistanceX;
    cellY = moveY - mouseDistanceY;

    //设置新的位置(偏移坐标)
    setPosition(this, { x: cellX, y: cellY });
  }

  function handleTouchEnd(e) {
    //获取空格盒子的高度和宽度(随便拿一个即可,其他盒子的宽高都一样)
    const blankWidth = oBlanks[0].offsetWidth,
      blankHeight = oBlanks[0].offsetHeight;

    //遍历空格池子里的盒子坐标数据
    for (let i = 0; i < blankAreas.length; i++) {
      //当某一项空格盒子没有被填充时
      if (resArr[i] !== undefined) {
        //忽略此轮循环下一轮
        continue;
      }

      /**
       * console.log(blankAreas);
       * [
       *   {startX: 8, startY: 8},
       *   {startX: 102, startY: 8},
       *   {startX: 196, startY: 8},
       *   {startX: 289, startY: 8}
       * ]
       */

      //获取当前某一个空白盒子偏移坐标
      let { startX, startY } = blankAreas[i];

      //对比字体盒子的覆盖面积大于空格盒子的1/2
      if (isOverBox(blankWidth, blankHeight, startX, startY)) {
        //修改移动当前的字体盒子的定位样式实现吸附功能
        setPosition(this, { x: startX, y: startY });

        //保存结果
        setResArr(this, i);

        /**
         console.log(resArr);
         * [
         *   {char: '画', el: div.wrapper},
         *   {char: '北', el: div.wrapper},
         *   {char: '团', el: div.wrapper},
         *   {char: '和', el: div.wrapper}
         * ]
         */

        //已经填满时
        if (!resArr.includes(undefined) && resArr.length === 4) {
          //延迟防止弹出警告框阻塞程序
          setTimeout(() => {
            //找不到结果时
            if (!checkResult()) {
              alert('答错了');
            } else {
              alert('答对了');
            }

            //回归位置
            resetPosition();
          }, 1000);
        }

        return;
      }
    }

    //获取某个字体盒子data-index
    const _index = Number(this.dataset.index);

    //获取拖动结束后的某一项的初始偏移量数据
    const charArea = charAreas[_index];
    // console.log(charArea);
    //{startX: 102, startY: 260}

    //设置回弹
    //修改移动当前的字体盒子的定位样式实现吸附功能
    setPosition(this, { x: charArea.startX, y: charArea.startY });
  }

  //判断对比字体盒子的覆盖面积大于空格盒子的1/2
  function isOverBox(blankWidth, blankHeight, startX, startY) {
    //空格盒子50%宽
    const halfBlankWidth = blankWidth / 2;
    //空格盒子50%高
    const halfBlankHeight = blankHeight / 2;

    // console.log(cellX, startX, cellX < startX + halfBlankWidth);

    //判断字体盒子左上角
    const flag1 =
      //1.宽度: 字体盒子左上角在空格盒子左上角的50%之内(进入)
      cellX > startX &&
      cellX < startX + halfBlankWidth &&
      //2.高度: 字体盒子左上角在空格盒子左上角的50%之内(进入)
      cellY > startY &&
      cellY < startY + halfBlankHeight;

    //判断字体盒子右上角
    const flag2 =
      //3.宽度: 字体盒子右上角在空格盒子右上角的50%之内(进入)
      cellX + blankWidth > startX + halfBlankWidth &&
      cellX + blankWidth < startX + blankWidth &&
      //4.高度: 字体盒子右上角在空格盒子右上角的50%之内(进入)
      cellY > startY &&
      cellY < startY + halfBlankHeight;

    return flag1 || flag2;
  }

  //设置位置 当前某一个空白盒子偏移坐标
  function setPosition(el, { x, y }) {
    el.style.left = pxToRem(x);
    el.style.top = pxToRem(y);
  }

  //通过缓存池获取初始偏移量数据
  function getAreas(domCollection, arrWrapper) {
    //回弹的初始位置
    let startX = 0,
      startY = 0,
      oItem = null;

    for (let i = 0; i < domCollection.length; i++) {
      oItem = domCollection[i];
      startX = oItem.offsetLeft;
      startY = oItem.offsetTop;

      //该池子保存所有字体盒子的偏移量数据
      arrWrapper.push({
        startX,
        startY
      });
    }

    // console.log(arrWrapper);
    //[{startX: 8, startY: 166}, {…}, {…}, ...]
  }

  //保存结果
  function setResArr(el, index) {
    resArr[index] = {
      char: el.innerText,
      el
    };
  }

  //回归位置
  function resetPosition() {
    resArr.forEach((item) => {
      const el = item.el,
        index = Number(el.dataset.index),
        { startX, startY } = charAreas[index];

      setPosition(el, { x: startX, y: startY });
    });

    //重置为初始值
    //该池子保存某个盒子的字体和节点
    resArr = [];
    startX = 0;
    startY = 0;
    cellX = 0;
    cellY = 0;
    mouseDistanceX = 0;
    mouseDistanceY = 0;
  }

  //检测结果
  function checkResult() {
    let idiom = '';

    //拼成一组
    resArr.forEach((item) => {
      idiom += item.char;
    });

    //查找答案池 返回找到的那一项成语 找不到返回undefined
    return idioms.find((item) => item === idiom);
  }

  function formatCharsArr() {
    let _arr = [];

    idioms.forEach((item) => {
      //1.以空字符为间隔拆开成语每个字
      //2.将每个字重组为新的数组
      //3.打乱数组内元素
      _arr = _arr.concat(item.split(''));
    });

    return _arr.sort(randomSort);

    // console.log(_arr);
    //['诗', '情', '画', '意', '南', '来', '北', '往', '一', '团', '和', '气', '落', '花', '流', '水']
  }

  function randomSort(a, b) {
    return Math.random() > 0.5 ? -1 : 1;
  }

  function pxToRem(value) {
    defaultFontSize = parseInt(defaultFontSize);

    return value / defaultFontSize + 'rem';
  }

  /**
   * 拼接某一项cell-item的模板
   * @param {*} char 字
   * @param {*} index 该索引用来找到某项的位置
   * @returns 视图模板
   */
  function charCellTpl(char, index) {
    return `
      <div class="cell-item">
        <div class="wrapper" data-index="${index}">${char}</div>
      </div>
    `;
  }

  //渲染模板
  function render() {
    let list = '';

    //遍历新charCollection数组
    charCollection.forEach((char, index) => {
      list += charCellTpl(char, index);
    });

    oCharCellGroup.innerHTML = list;
  }

  init();
})();
